package com.lagou.rabbitmq.controller;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.lagou.rabbitmq.constants.OrderConstants;
import com.lagou.rabbitmq.constants.RabbitConstants;
import com.lagou.rabbitmq.domain.Order;
import com.lagou.rabbitmq.handler.StockMessage;
import com.lagou.rabbitmq.service.OrderService;
import com.lagou.rabbitmq.vo.OrderVo;
import com.lagou.rabbitmq.vo.R;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessageProperties;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;

import java.util.Date;
import java.util.Random;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

/**
 * @className: OrderController
 * @auther: Jerry
 * @date: 2021/3/17 22:35
 * @desctiption: TODO
 * @version: 1.0
 */
@RestController
@RequestMapping("/order")
public class OrderController {

    @Autowired
    private OrderService orderService;

    @Autowired
    private AmqpTemplate amqpTemplate;

    @Autowired
    private StringRedisTemplate redisTemplate;

    private final String ORDER_PREFIX = "orderId::";

    @RequestMapping("/list")
    public R list(@RequestParam(value = "page", required = false, defaultValue = "1") Integer pageNo,
                  @RequestParam(value = "limit", required = false, defaultValue = "10") Integer pageSize,
                  @RequestParam(value = "orderState", required = false) String orderState) {

        LambdaQueryWrapper<Order> wrapper = new LambdaQueryWrapper<Order>();
        if (!StringUtils.isEmpty(orderState)) {
            wrapper.eq(Order::getOrderState, orderState);
        }
        Page pageParam = new Page(pageNo, pageSize);
        Page page = orderService.page(pageParam, wrapper);
        return R.ok(page);
    }

    @RequestMapping(value = "/submit", produces = "application/json;charset=UTF-8")
    public R submit(@RequestBody OrderVo orderVo) {
        String token = UUID.randomUUID().toString();
        // 密等校验
        Boolean result = redisTemplate.opsForValue().setIfAbsent(ORDER_PREFIX + orderVo.getGoodsId(),
                token, 10, TimeUnit.SECONDS);
        if (!result) {
            return R.error("请勿重复操作");
        }

        Order order = orderService.createOrder(orderVo);
        System.out.println("OrderController.submit... createOrder");
        // 扣减库存
        amqpTemplate.convertAndSend(RabbitConstants.STOCK_EXCHANGE,
                RabbitConstants.STOCK_ROUTING_KEY,
                new StockMessage(orderVo.getGoodsId(),
                        order.getQuantity(),
                        StockMessage.REDUCE_STOCK));
        System.out.println("OrderController.submit... sendMessage to stockExchange");

        // 超时未支付放入死信队列
        amqpTemplate.convertAndSend(RabbitConstants.ORDER_EXCHANGE,
                RabbitConstants.ORDER_ROUTING_KEY,
                (order.getId() + ""));
        System.out.println("OrderController.submit... sendMessage to orderExchange");
        return R.ok(order);
    }

    @RequestMapping("/detail/{orderId}")
    public R detail(@PathVariable("orderId") Long orderId) {
        Order order = orderService.getById(orderId);
        return R.ok(order);
    }

    @RequestMapping("/pay/{orderId}")
    public R pay(@PathVariable("orderId") Long orderId) {
        Order o = orderService.getById(orderId);
        Order order = new Order();
        order.setId(o.getId());
        order.setGmtModified(new Date());
        if (OrderConstants.CANCEL.getCode().equals(o.getOrderState())) {
            // 订单取消，要把库存加回去
            amqpTemplate.convertAndSend(RabbitConstants.STOCK_EXCHANGE,
                    RabbitConstants.STOCK_ROUTING_KEY,
                    new StockMessage(o.getGoodsId(),
                            o.getQuantity(),
                            StockMessage.ADD_STOCK));
            return R.error("已超时，订单取消");
        }
        order.setOrderState(OrderConstants.PAIED.getCode());
        orderService.updateById(order);
        return R.ok("付款成功");
    }

}
